home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-20
/
rs0422.zip
/
CONFIGUR
/
CONFIG.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-10-26
|
14KB
|
532 lines
/*
* Copyright 1988 by the Radio Amateur Telecommunications Society
* and Thomas A. Moulton, W2VY
*
* This software may only be modified, copied, distributed or
* executed for non-profit purposes by individuals operating
* systems in the Amateur Radio Service. Credit to the
* author(s) and to the Radio Amateur Telecommunications Society
* must be made in modules where RATS provided software is used,
* and in any announcements and documentation.
*
* As a non-profit, research and development organization, the
* Radio Amateur Telecommunications Society distributes software
* in both executable and source forms. This policy is in place
* to encourage the development and distribution of OSI-based,
* networking tools. In order to protect the interests of the
* Society and the authors, we have placed some conditions
* of use on the software. Other groups are encouraged
* to place the same or similar guidelines on
* software they produce.
*
* The Radio Amateur Telecommunications Society reserves the right
* to specify and alter the terms under which software provided by
* the Society may be used. This policy is consistent with the
* objective of uniform and consistent "Open Systems Interconnections."
*
* All acceptable Amateur Radio related uses of this software
* will be outlined in the "ROSE Implementer's Guide". Individuals
* or organizations wishing to add to, or modify the provisions of
* the guide to accommodate local or evolutionary requirements
* should document the proposed change(s) and forward them to the
* Society. If accepted, written notification will be provided by
* the Society to the submitting organization or individual(s).
* The Society will then issue a "ROSE Implementer's Guide Change
* Notice". Periodically, the Society will re-issue the "ROSE
* Implementer's Guide" and incorporate the text of the change
* notices. This procedure has been put in to place to ensure
* compatibility between systems and to ensure their "Openness"
* and interoperability.
*
* No part of this software may be used in other packages
* without prior authorization from the author or the Society.
* Software incorporating this module, all or in part, must be
* provided to the Society prior to distribution or use by
* anyone not directly involved in testing of the revised
* environment. Current releases of the combined software must
* be provided to the Society in both source and executable
* forms. Adequate documention to produce an executable module
* from the provided source must also be included.
*
* Non-Amateur Radio non-profit uses may be authorized on a case
* by case basis. Inquiries for such use may be made in writing
* to the Society. Non-commercial uses consistent with the
* general principles of Open Systems Interconnection Reference
* Model will be generally considered with favor.
*
* Commercial licensing of the software is also available based
* on normal commercial terms. Licensing inquiries should be
* directed to the Society. Commercial licensing of the standard
* software will be done in situations which materially benefit
* the Amateur Radio Packet Network. Additional licensing is
* reserved by the individual authors.
*
* The Radio Amateur Telecommunications Society provides this software
* on an "as is" basis. The Society assumes no liability for
* loss incurred through the use of this software. Amateur Radio
* use of this software implies non-commercial and voluntary
* development, deployment and use of this software in a "Amateur",
* non-commercial service. Commercial users are encouraged to
* inspect their copies of the source code. Source code modification
* licenses are available if a combined Object and Source Code
* license was not originally established.
*
* The Society may be contacted by writing or calling at:
*
* The Radio Amateur Telecommunications Society
* 206 North Vivyen Street.
* Bergenfield, New Jersey 07621
*
* Telephone: 201-387-8896
*
*/
#include "data.h"
#include "buffer.h"
#include "iface.h"
#include "timer.h"
#include "ax25.h"
#include "ax25l2.h"
#include "l3struc.h"
#include "x25cause.h"
#include "l3calls.h"
#include "tx.h"
#include "config.h"
#include "upfcn.h"
int NULLFCN(), clr_config(), con_config(), recv_boot();
int send_config(), rst_boot(), unload_ok();
struct upfcn config={
{{0x86, 0x9e, 0x9c, 0x8c, 0x92, 0x8e}, {0x00}}, /* CONFIG-0 */
rst_boot, clr_config, con_config, recv_boot,
send_config, NULLFCN, unload_ok,
"CONFIG - ROSE X.25 Packet Switch Configuration Interface Ver 2.3\r"
};
extern unsigned char node_addr[];
extern int userport;
extern struct ax25_parms *l2parms, *l3parms;
extern struct datastr *l2_user_info, l2_info;
extern unsigned char NPAroute[][16];
extern unsigned char RTable[];
extern unsigned char passlen;
#define cnf_clrdta() free_stuff(&save_cnf_data)
struct datastr *mkpkt();
int check_x121();
unsigned char *malloc(), *calloc();
void free();
int bss_i(), usr_info(), rt_init(), examod_i();
int buf();
#define READONLY 0x80
#define MUSTCLEAR 0x40
#define RESET 0x20
#define DYNAMIC 0x10
#define BAD_OBJ 0x08
#define FCNCALL 0x01
/* MUSTCLEAR says to update this we need to clear all links */
/* RESET says we can reset this after a read */
/* DYNAMIC says the Object is a pointer pointing to malloc'ed memory */
/* BAD_OBJ Says the object is not supported */
/* FCNCALL says to call *fcn() to copy byte */
struct inftab {
void *obj; /* Pointer to the object we are working with */
int len; /* It's length (number of items) */
int size; /* it's size (bytes/item) */
char flags; /* Special handling flags */
int (*init)(); /* Set up vars for get/put */
int (*fcn)(); /* Function to handle one byte */
};
struct inftab inf[MAXOBJ] = {
{&l2_user_info,1,0,DYNAMIC+FCNCALL,usr_info,buf},
{L3CALL,L3SIZ,AXALEN,0,bss_i,NULL},
{L3DIGI,L3SIZ,AXALEN,0,bss_i,NULL},
{L3PORT,L3SIZ,1,0,bss_i,NULL},
{L3_MAXVC,L3SIZ,1,0,bss_i,NULL},
{L3_WI,L3SIZ,1,0,bss_i,NULL},
{L3DELAY,16,2,0,bss_i,NULL},
{&userport,1,sizeof(int),0,bss_i,NULL},
{node_addr,1,7,0,bss_i,NULL},
{&l2parms,1,sizeof(struct ax25_parms),DYNAMIC,bss_i,NULL},
{&l3parms,1,sizeof(struct ax25_parms),DYNAMIC,bss_i,NULL},
{NPAroute,1,16*16,0,bss_i,NULL},
{RTable,1,2048,0,bss_i,NULL},
{&passlen,1,257,0,bss_i,NULL},
{NULL,1,0,READONLY,bss_i,NULL},
{NULL,0,1,DYNAMIC,examod_i,NULL}
};
#define WRITE 01
#define READ 02
#define READR 03
#define MAXCMD 03
#if 0
char *errmsg[]={
"Invalid command\n",
"Invalid Object specified\n",
"No working memory!\n",
"Bad checksum!\n",
"Not implemented yet, sorry\n"
"Odd number of data bytes for type\n"
"Item is Read-Only"
};
#endif
char cnf_busy;
char cnf_state;
struct datastr *cnf_in;
char cnf_cmd;
char cnf_obj;
int cnf_len;
int cnf_pos;
unsigned char *cnf_data, *save_cnf_data;
unsigned char cnf_checksum;
char cnf_high;
unsigned char cnf_chv;
#if 0
int
hexch(ch)
unsigned char ch;
{
if (ch>0x39) ch -= 7;
if (ch<0x30 || ch>0x3f) return -1;
return (ch-0x30);
}
int
xch(val)
unsigned char val;
{
val = (val & 0x0f);
if (val > 9) val += 7;
return (val + 0x30);
}
putxch(p,val)
register struct datastr *p;
int val;
{
bappch(p,xch(val >> 4));
bappch(p,xch(val));
}
putxint(p,val)
register struct datastr *p;
int val;
{
putxch(p,val); /* Low byte Low address */
putxch(p,(val>>8));
}
#endif
int
con_config(vc)
register struct VCS *vc;
{
vc=vc->peer;
if (!vc) return;
puthex2("con",vc,"at",fn);
send_l3(vc,info_pkt());
if (cnf_busy) vc_clear(vc->peer,Number_Busy);
else {
cnf_busy = 1;
cnf_state = 1;
}
}
int
clr_config(vc,c)
struct VCS *vc;
int c;
{
cnf_busy = 0;
/* cnf_clrdta(); Not sure if we should do this */
set_p(vc, P1, 0);
}
int
send_config(vc, pkt)
register struct VCS *vc;
struct datastr *pkt;
{
static int i, ch;
int hexch();
puthex2("send fig",vc,"",pkt);
vc_queue_data(vc,pkt);
while ((cnf_in = vc->tx_queue)) /* There is stuff waiting */ {
vc->tx_queue=cnf_in->next;
cnf_in->next=NULL;
while ((ch=bgetch(&cnf_in)) != EOF) {
puthex2("loop",ch,"",cnf_in);
if (ch > 0x20) /* Allow Control chars to pass */ {
i=hexch(ch);
if (ch == 0x3a || i<0 ) cnf_state=1;
if (cnf_state == 1) /* Clean Up */ {
cnf_clrdta();
cnf_data = NULL;
cnf_chv = ch;
cnf_high = TRUE;
} else {
if (cnf_high) cnf_chv = i<<4;
else cnf_chv += i;
cnf_high = !cnf_high;
}
if (cnf_high) cnf_next(vc, cnf_chv);
}
}
}
return 256; /* We are never busy! */
}
/* cnf_state has the following meaning
/* 1 - Searching for a : (Start of record)
/* 2 - Next byte read is the command
/* 3 - Next byte read is the object we are working with
/* 4 - Next byte read is the low byte of length !Low byte Low address!
/* 5 - Next byte read is the high byte of length
/* 6 - Next byte read is additional data
/* 7 - Processing request
*/
cnf_next(vc,chv)
struct VCS *vc;
unsigned char chv;
{
static char err;
static int len;
register struct VCS *vcp;
static struct inftab *rec;
int do_config();
err=0;
vcp=vc->peer;
puthex2("next",cnf_state,"ch",chv);
switch (cnf_state) {
case 1: if (chv != 0x3a) cnf_state=0;
break;
case 2: cnf_cmd=chv;
if (chv>MAXCMD) err=1;
break;
case 3: cnf_obj=chv;
if (chv>MAXOBJ) err=2;
else if (inf[cnf_obj].flags & BAD_OBJ) err=2;
break;
case 4: cnf_len= chv; /* Low byte Low address */
break;
case 5: cnf_len += (chv<<8);
cnf_pos=0;
cnf_checksum=0;
rec = &inf[cnf_obj];
len= rec->size * rec->len;
if (rec->flags & DYNAMIC) len=cnf_len;
if (len) /* && cnf_cmd == WRITE) */ {
cnf_data=save_cnf_data=calloc(1,len);
if (cnf_data == NULL) err=3;
}
if (cnf_len == 0) cnf_state++; /* No data field */
break;
case 6: cnf_data[cnf_pos]=chv;
cnf_pos++;
cnf_checksum += chv;
if (cnf_pos != cnf_len) cnf_state--;
break;
case 7: cnf_checksum += chv;
if (cnf_checksum != 0) err=4;
else err=do_config(vcp);
if (!err) send_l3(vcp,mkpkt("OK\r"));
cnf_clrdta();
cnf_state=0;
break;
}
if (err) {
if (vcp) send_l3(vcp, l_message(" Error ", err));
cnf_state=0;
}
cnf_state++;
puthex2("exit",cnf_state,"err",err);
}
int
do_config(vc)
struct VCS *vc;
{
static int j, len;
static struct datastr *bp;
register struct inftab *rec;
static unsigned char *ch, *ch1;
puthex2("do it",cnf_cmd,"",cnf_obj);
rec = &inf[cnf_obj];
len = (*rec->init)(rec, &ch);
if (len < 0) return -len;
if (cnf_cmd == WRITE) {
if (rec->flags & READONLY) return 7;
ch1 = (unsigned char *)cnf_data;
while (len>0) {
len--;
if (rec->flags & FCNCALL) {
(*rec->fcn) (&ch, &ch1, len);
ch1++;
}
else *ch++ = *ch1++;
}
sumchk(); /* Reset the checksum for bbRAM */
}
else if (cnf_cmd == READ) {
bp=new_buffer((len*2)+10);
if (!bp) return 3;
bappch(bp,0x3a);
putxch(bp,cnf_obj); /* Identify what we are sending */
putxint(bp,len); /* and how big it is */
cnf_checksum=0;
while (len > 0) {
len--;
if (rec->flags & FCNCALL)
j = (*rec->fcn)(&ch, NULL, len);
else j = *ch++;
cnf_checksum += j;
putxch(bp,j);
}
putxch(bp,-cnf_checksum);
bappch(bp,0x0d);
send_l3(vc,bp);
}
else return 5;
return 0;
}
usr_info(rec,ch)
struct inftab *rec;
struct datastr **ch;
{
register struct datastr *bp;
static int len;
if (cnf_cmd == WRITE) {
if (l2_user_info != &l2_info) free_pkt(l2_user_info);
l2_user_info=dup_pkt(&l2_info);
len = cnf_len;
bp=new_buffer(len);
if (!bp) return -1;
l2_user_info=binsert(l2_user_info,bp);
}
else /* It's Read (or ReadR) */ {
bp=dup_pkt(l2_user_info); /* Leave orig. alone */
if (!bp) len = -1;
else len = buflen(bp);
}
*ch = bp;
return len;
}
int
buf(bpx,ch,left)
struct datastr **bpx;
unsigned char **ch;
int left; /* Number of bytes (aka calls) left */
{
static int c;
if (cnf_cmd == WRITE) bappch(*bpx,**ch);
else /* Read */ {
if (*bpx == NULL) return EOF;
c=bgetch(bpx);
if (!left) free_stuff(bpx);
return c;
}
}
int
bss_i(rec,ch)
register struct inftab *rec;
unsigned char **ch;
{
static unsigned char *ch1;
ch1 = (unsigned char *)rec->obj;
if (rec->flags & DYNAMIC) ch1 = *(unsigned char **)ch1;
*ch = ch1;
return (rec->size * rec->len);
}
#if 0
int
rt_init(rec,ch)
struct inftab *rec;
unsigned char **ch;
{
static int i, j, k, l, nd, c;
static struct dnic dn;
for (i=0;i<3;i++) {
if (cnf_len <= 0) return -6;
cnf_len--;
c = *cnf_data++;
dn.adr[i] = c;
}
for (i=0;i<ndnics;i++) {
if (check_x121(DNics[i].adr,dn.adr) >= 0) break;
}
if (cnf_cmd == WRITE) {
*ch = NULL; /* Invalid DNIC */
if (i<ndnics) free_stuff(&DNics[i].rt);
l = cnf_len;
if (cnf_len == 0) /* Delete DNIC */ {
if (i == ndnics) return 0; /* Deleted Invalid DNIC */
nd = ndnics-1;
if (i == nd) ndnics--;
else /* Have to copy rest... */ {
for (j=i;j<nd;j++) {
for (k=0;k<3;k++)
DNics[j].adr[k] = DNics[j+1].adr[k];
DNics[j].rt = DNics[j+1].rt;
}
}
}
else /* Add Dnic */ {
if (i == ndnics) {
ndnics++;
for (j=0;j<3;j++) DNics[i].adr[j] = dn.adr[j];
}
else free_stuff(&DNics[i].rt);
DNics[i].rt = *ch = malloc(cnf_len);
DNics[i].len = cnf_len;
}
}
else /* READ */ {
if (i == ndnics) return -2; /* Invalid DNIC */
*ch = DNics[i].rt;
l = DNics[i].len;
}
return l;
}
#endif
int
examod_i(rec,ch)
struct inftab *rec;
unsigned char **ch;
{
static int len;
register unsigned int *dta;
if (cnf_len < 4) return -6;
dta = (unsigned int *) cnf_data;
*ch = (unsigned char *) *dta;
len = *(dta+1);
cnf_data += 4;
cnf_len -= 4;
return len;
}